package com.jianwei.web.dao;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.util.Date;
import java.util.List;

import javax.persistence.Id;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;

import com.jianwei.web.util.PageUtil;


public class BaseDao<M extends Serializable,PK extends Serializable> {
	
	@Autowired
	private SessionFactory sessionFactory;
	private final Class<M> entityClass;
    private final String HQL_LIST_ALL;
	private final String HQL_COUNT_ALL;
    private String pkName = null;
    
	@SuppressWarnings("unchecked")
	public BaseDao(){
		this.entityClass = (Class<M>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
        Field[] fields = this.entityClass.getDeclaredFields();
        for(Field f : fields) {
            if(f.isAnnotationPresent(Id.class)) {
                this.pkName = f.getName();
            }
        }
        Assert.notNull(pkName);
        //TODO @Entity name not null
        HQL_LIST_ALL = "from " + this.entityClass.getSimpleName() + " order by " + pkName + " desc";
        HQL_COUNT_ALL = " select count(*) from " + this.entityClass.getSimpleName();
	}
	
	public void save(M model){
		getSession().save(model);
	}
	
	public void saveOrUpdate(M model){
		getSession().saveOrUpdate(model);
	}
	
	public void update(M model){
		getSession().update(model);
	}
	
	@SuppressWarnings("unchecked")
	public List<M> findAll(){
		return getSession().createQuery(HQL_LIST_ALL).list();
	}
	
	@SuppressWarnings("unchecked")
	public PK findCount(){
		return (PK) getSession().createQuery(HQL_COUNT_ALL).uniqueResult();
	}
	
	/**
	 * 查询所有数据,根据分页
	 * @param pn　页数，第几页
	 * @param pageSize　每页显示条数
	 * @return 
	 */
	@SuppressWarnings("unchecked")
	public List<M> fundAllByPage(final int pn, final int pageSize) {
		Query query = getSession().createQuery(HQL_LIST_ALL);
		if (pn > -1 && pageSize > -1) {
			query.setMaxResults(pageSize);
			int start = PageUtil.getPageStart(pn, pageSize);
			if (start != 0) {
				query.setFirstResult(start);
			}
		}
		if (pn < 0) {
			query.setFirstResult(0);
		}
		return query.list();
	}
	
	/**
	 * 根据条件,进行分页查询
	 * @param hql 查询语句
	 * @param pn　页数，第几页
	 * @param pageSize　每页显示条数
	 * @param paramlist 条件集合
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public List<M> fundAllByPage(final String hql,final int pn, final int pageSize,final Object... paramlist) {
		Query query = getSession().createQuery(hql);
		setParameters(query, paramlist);
		if (pn > -1 && pageSize > -1) {
			query.setMaxResults(pageSize);
			int start = PageUtil.getPageStart(pn, pageSize);
			if (start != 0) {
				query.setFirstResult(start);
			}
		}
		if (pn < 0) {
			query.setFirstResult(0);
		}
		return query.list();
	}
	
	/**
	 * 根据条件查询数据
	 * @param hql 查询语句
	 * @param paramlist 查询条件
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public List<M> findByParam(final String hql,Object... paramlist){
		Query query = getSession().createQuery(hql);
		setParameters(query, paramlist);
		return query.list();
	}
	
	/**
	 * 给查询设置查询条件
	 * @param query
	 * @param paramlist 条件集合
	 */
	public void setParameters(Query query, Object[] paramlist) {
        if (paramlist != null) {
            for (int i = 0; i < paramlist.length; i++) {
            	//instanceof 关键字用来判断 左边的对象的实例 是否与右边相同
                if(paramlist[i] instanceof Date) {
                    //TODO 难道这是bug 使用setParameter不行？？
                    query.setTimestamp(i, (Date)paramlist[i]);
                } else {
                    query.setParameter(i, paramlist[i]);
                }
            }
        }
    }
	
	public Session getSession(){
		return sessionFactory.getCurrentSession();
	}
}
